<?php
Zend::loadClass('Lead_Event_Observable_Abstract');

/**
 * @package EDO
 * @subpackage Core
 *
 */
abstract class Lead_EDO_Object_Base extends Lead_Event_Observable_Abstract 
{
	// static protected $_typedata = array();
    static private $_massData = array();
	
    
    
    
    
   	protected $tables;
	protected $tables_fields;
	protected $fields_tables;
	protected $fields_validables;

    
    
    
   	protected $_fieldarray = array();
	protected $_relationarray = array();

    
    
    
    /**
     * Finder
     *
     * @var EDOFinder
     */
    protected $_finder;
    
    
	
	/**
	 * Handler
	 *
	 * @var EDOHandler
	 */
	public $edo;


	/**
	 * LDB object
	 *
	 * @var LDB_base
	 */
	public $ldb;




	protected $_typeData;


	public function __construct(Lead_EDO_Handler_Interface $edo_handler)
	{
		$this->edo = $edo_handler;
		$this->ldb = $edo_handler->ldb;
	}


	public function __destruct()
	{

	}



	/**
	 * Clears typedata
	 *
	 * @todo Fix.
	 *
	 */
	public function clear()
	{
		die('clear doesnt work now');

	    foreach(self::$_typedata[$this->getClass()] as $typedatakey => $typedatavalue)
		{
			$this->$typedatakey = $typedatavalue;
		}
	}

	
	
	protected function __call($method, $args)
	{
        if($this->fieldExists($method))
            return $this->getFieldObject($method);
            
        
        throw new Exception("'{$method}' field object or method does not exist for EDO and was not trapped in __call");
            
	}
	
	

	/**
	 * Overloads the getting of class properties in the fieldarray.
	 *
	 * @param string $key Field name
	 * @return mixed Field value
	 */
	protected function __get($key)
	{
		if(key_exists($key, $this->_fieldarray))
		{
			return $this->getField($key);
		}
		
		throw new Exception("Field '{$key}' does not exist in EDO.");
	}

	/**
	 * Overloads the setting of class properties in the fieldarray.
	 *
	 * @param string $key Field name
	 * @param mixed $value Field value
	 * @return boolean Success or not.
	 */
	protected function __set($key, $value)
	{

		if(key_exists($key, $this->_fieldarray))
		{
			return $this->setField($key, $value);
		}
		
			throw new Exception("Field '{$key}' does not exist in EDO.");


	}


	/**
	 * Sets masses of fields from a raw associative array.
	 *
	 * @param array $fieldarray
	 */
	public function setFields($fieldarray)
	{
		

		foreach($fieldarray as $fieldkey => &$fieldvalue)
		{
			if(key_exists($fieldkey, $this->_fieldarray))
			{
				$this->setField($fieldkey, $fieldvalue);
			}
		}
	}


	/**
	 * Returns the EDO class of the dataobject.
	 *
	 * @return string
	 */
	public function getClass()
	{
		return get_class($this);
	}


	/**
	 * Sets a field value.
	 *
	 * @param string $key Field name
	 * @param mixed $value Field value
	 * @return boolean Success or not
	 */
	public function setField($key, $value)
	{
		$success = $this->_fieldarray[$key]->setValue($value);

		return ($success === false) ? false : true;
	}

	/**
	 * Returns the value of a field.
	 *
	 * @param string $key Field name
	 * @return mixed Field value
	 */
	public function getField($key)
	{
		return $this->getFieldObject($key)->getValue();
	    
	    // return $this->_fieldarray[$key]->getValue();
	}

	public function getFieldForSQL($key)
	{
		return (is_callable(array($this->_fieldarray[$key], 'getValueForSQL'))) ? $this->_fieldarray[$key]->getValueForSQL() : $this->_fieldarray[$key]->getValue();
	}


	public function getFieldForDisplay($key)
	{
		return $this->_fieldarray[$key]->getDisplayValue();
	}



	/**
	 * Returns the field object for a field.
	 *
	 * @param string $key Field name
	 * @return Datatype_base Datatype object
	 */
	public function getFieldObject($key)
	{
		if(isset($this->_fieldarray[$key]))
	       return $this->_fieldarray[$key];
	       
	    return false;
	}


	public function getFieldsType($fieldName)
	{
		return $this->getFieldObject($fieldName)->getType();
	}



	/**
	 * Returns a relation from relationarray.
	 *
	 * @param string $key Relation name
	 * @return unknown
	 */
	public function getRelation($key)
	{
		if(key_exists($key, $this->_typeData['relations']))
            return $this->_typeData['relations'][$key];

        throw new Exception("Relation '{$key}' not found.");
	}


	/**
	 * Returns an array containing the object's relations.
	 *
	 * @return array
	 */
	public function getRelations()
	{
        return $this->_typeData['relations'];
	}



	/**
	 * Returns fields tables id.
	 *
	 * @param string $fieldName Field name
	 * @return integer
	 */
	public function getFieldsTableId($fieldName)
	{
		return array_search($fieldName, $this->getTables());
	}

	/**
	 * Returns fields tables name.
	 *
	 * @param string $fieldName Field name
	 * @return
	 */
	public function getFieldsTable($fieldName)
	{
	    if(isset($this->_typeData['fields_tables'][$fieldName]))
	       return $this->_typeData['fields_tables'][$fieldName];
	       
	    return false;
	}



	/**
	 * Returns the dataobjects raw field array.
	 *
	 * @return unknown
	 */
	public function getFieldArray()
	{
		return $this->_fieldarray;

	}





	/**
	 * Returns datobjects fields.
	 *
	 * @return array the fields.
	 */
	public function getFields()
	{
		return array_keys($this->_typeData['fields_tables']);
	}
	
	public function getFieldObjects()
	{
	    return $this->_fieldarray;
	}
	
	
	public function getRelationObjects()
	{
	    $relArr = array();
	    foreach($this->getRelations() as $relation)
	    {
	        $relArr[] = $this->getFieldObject($relation['name']);
	    }
	    return $relArr;
	}
	
	
	

	/**
	 * Returns dataobjects tables.
	 *
	 * @return array The tables.
	 */
	public function getTables()
	{
		return $this->_typeData['tables'];
	}
	
	public function getFirstTable()
	{
	    $tables = $this->getTables();
	    return array_shift($tables);
	}
	
	public function getRestOfTables()
	{
	    $tables = $this->getTables();
	    array_shift($tables);
	    return $tables;
	}
	
	
	
	public function tableIsDimensional($table)
	{
	    return (in_array($table, $this->getDimensionalTables()));
	}
	
	
	public function getDimensionalTables()
	{
	    return $this->_typeData['dimensional_tables'];
	}
	

	/**
	 * Returns fields in a table.
	 *
	 * @param mixed $tableid Tables name or id
	 * @return array
	 */
	public function getTablesFields($tableid)
	{			    
	    if(!is_numeric($tableid))
		{
			$tableid = $this->tableNameToTableId($tableid);
		}

		return $this->_typeData['tables_fields'][$tableid];
	}


	/**
	 * Converts table name to table id.
	 *
	 * @param string $tableName Table name
	 * @return integer
	 */
	public function tableNameToTableId($tableName)
	{
		$key = array_search($tableName, $this->getTables());
		return $key;
	}


	public function tableIdToTableName($tableId)
	{
	    $tables = $this->getTables();
	    return $tables[$tableId];

	}


	public function getTable($tableId)
	{
	    if(is_numeric($tableId))
	    {
	        $tableId = $this->tableIdToTableName($tableId);
	    }

	    $tableObj = $this->ldb->getTable($tableId);
	    return $tableObj;
	}




	public function getFieldsOfType($dataType)
	{
		$fieldNames = array();

		foreach($this->getFields() as $field)
		{
			$dObject = $this->getFieldObject($field);
			if($dObject->getType() == $dataType)
				$fieldNames[] = $field;
		}
		return $fieldNames;
	}




	/**
	 * Returns dataobjects fields and tables.
	 *
	 * @return array
	 */
	public function getFieldsAndTables()
	{
		return $this->_typeData['fields_tables'];
	}


	/**
	 * Returns an assoc array in format 'tablename' => array('field1_name','field2_name')
	 *
	 * @return Array
	 */
	public function getTableFieldNameArray()
	{
		$resultArr = array();
		foreach($this->getTables() as $tbl)
		{
			// $tableid = $this->tableNameToTableId($tbl);
			foreach($this->getFieldsAndTables() as $f => $t_id)
				if($t_id == $tbl)
					$resultArr[$tbl][] = $f;
		}
		return $resultArr;
	}


	/**
	 * Saves the dataobject.
	 *
	 * @param integer $clear If 1, ensures that a new edoid is assigned. Wooooot?
	 * @return boolean Success or not.
	 */
	public function save()
	{
		return $this->edo->save($this);
	}



	/**
	 * Enter description here...
	 *
	 * @param integer $clear If 1, ensures that a new edoid is assigned. Use if unsure.
	 * @return boolean Success or not
	 */
	public function insert($clear = true)
	{
		return $this->edo->insert($this, $clear);
	}



	/**
	 * Deletes the dataobject. There is no coming back.
	 *
	 * @return boolean Success or not.
	 */
	function delete()
	{
		$deleted = $this->edo->delete($this);
		if($deleted)
		{
		    $this->triggerEvent('onDelete');
		}
		return $deleted;
	}
	
		
	public function deleteAll($conditions = array())
	{
	    
	    
	}
	


	
	/**
	 * Returns object's Finder object.
	 *
	 * @return EDOFinder
	 */
	public function getFinder()
	{
	    if(!$this->_finder)
	    {
            require_once Lead_EDO::getRoot() . '/Core/EDOFinder/EDOFinder.php';
            $this->_finder = new EDOFinder($this);
	    }
	    
	    return $this->_finder;
	}
	
	
	
	
	
	
	


	public function getHandler()
	{
		return $this->edo;
	}




	public function getRawFields()
	{
	    return $this->_typeData['fields_raw'];
	}




	protected function _initDataTypes()
	{
    	    
	    $datatypeArr = array_merge($this->getRawFields(), $this->getRelations());
        
	    foreach($datatypeArr as $fieldName => &$fieldData)
		{
			$datatype = $fieldData['type'];

			Zend::loadClass('Lead_EDO_Datatype_Factory');
					
			$datatypeObj = Lead_EDO_Datatype_Factory::factory($this, $datatype, $fieldData);
			$this->_fieldarray[$fieldName] = $datatypeObj;
		}
		
	}


	public function fieldExists($fieldName)
	{
	    return (key_exists($fieldName, $this->_fieldarray)) ? true : false;
	}


	public function getRelationsClasses()
	{
	    return $this->_typeData['relations_classes'];
	}
	
	
}

?>